package cn.qpyl.longpoll.netty;

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.concurrent.*;
import java.util.function.Consumer;
import java.util.function.Function;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class EventLoop implements Runnable {

    private int maxQueueSize = 1000;
    private boolean stop = false;
    private final Executor executor;
    private final Executor threadExecutor;

    public EventLoop(final String eventloopName) {
        executor = Executors.newSingleThreadExecutor(r -> new Thread(r, eventloopName));
        threadExecutor = Executors.newCachedThreadPool();
        executor.execute(this);
    }

    @Override
    public void run() {
        do {
            long now = System.currentTimeMillis();

            {
                repeatedMap.forEach((k, v) -> {
                    if (!v.active) {
                        threadExecutor.execute(v);
                        v.active();
                    } else {
                        repeatedMap.remove(k);
                    }
                });
            }

            {
                Task t = onceQueue.peek();
                if (null != t) {
                    if (!t.done) {
                        if (t.delay <= now) {
                            t = onceQueue.poll();
                            threadExecutor.execute(t);
                        }
                    }
                }
            }
            try {
                Thread.sleep(100L);
            } catch (Exception e) {
            }

        } while (!confirmShutdown());
    }

    private boolean confirmShutdown() {
        return stop;
    }

    /**
     * 队列中包含的最大任务个数
     *
     * @param maxQueueSize 任务个数
     */
    public void setMaxQueueSize(final int maxQueueSize) {
        this.maxQueueSize = maxQueueSize;
    }

    class Task implements Runnable {

        boolean active = false; // 是否激活
        boolean done = false; // 是否成功执行
        long internal = 0L; // 执行间隔
        long timeout = 0L;// 执行超时
        long delay = 0L;// 延迟
        long recentExecTime = 0L;

        Function<?, Boolean> func;

        public Task(Function<?, Boolean> f) {
            func = f;
        }

        public Task internal(long i) {
            internal = i;
            return this;
        }

        public Task timeout(long to) {
            timeout = System.currentTimeMillis() + to;
            return this;
        }

        public Task delay(long d) {
            delay = System.currentTimeMillis() + d;
            return this;
        }

        public void once() {
            active = false;
            done = false;
        }

        public void repeated() {
            active = false;
            done = false;
        }

        @Override
        public void run() {
        }

        public void active() {
            active = true;
        }

        public int compare(Task t) {
            if (this.delay > t.delay) {
                return 1;
            } else if (this.delay < t.delay) {
                return -1;
            }
            return 0;
        }
    }

    class RepeatTask extends Task {

        public RepeatTask(Function<?, Boolean> f) {
            super(f);
        }

        @Override
        public void run() {
            if (internal <= 0) {
                internal = 1000L;
            }
            while (!done) {
                if (func.apply(null)) {
                    done = true;
                }
                try {
                    Thread.sleep(internal);
                } catch (Exception e) {
                }
            }
        }
    }

    class OnceTask extends Task {

        public OnceTask(Function<?, Boolean> f) {
            super(f);
        }

        @Override
        public void run() {
            if (func.apply(null)) {
                done = true;
            }
        }
    }

    // 重复执行任务
    ConcurrentHashMap<Integer, Task> repeatedMap = new ConcurrentHashMap<>();
    // 单次执行任务
    PriorityQueue<Task> onceQueue = new PriorityQueue<>(maxQueueSize, new Comparator<Task>() {

        @Override
        public int compare(Task t1, Task t2) {
            return t1.compare(t2);
        }

    });

    /**
     * 创建重复任务
     * 
     * @param func
     * @param internal
     * @param timeout
     * @return
     */
    public Consumer<Object> createRepeatTask(final Function<Object, Boolean> func, final long internal,
            final long timeout) {

        Task t = new RepeatTask(func);
        t.internal(internal).timeout(timeout).repeated();
        repeatedMap.putIfAbsent(t.hashCode(), t);

        final Consumer<Object> c = new Consumer<Object>() {

            boolean done = false;

            @Override
            public void accept(final Object t) {
                if (!done) {
                    if (func.apply(t)) {
                        done = true;
                    }
                }
            }
        };

        return c;
    }

    /**
     * 创建一次性任务
     * 
     * @param func
     * @param delay
     * @return
     */
    public Consumer<Object> createOnceTask(final Function<Object, Boolean> func, final long delay) {

        Task t = new OnceTask(func);
        t.delay(delay).once();
        onceQueue.offer(t);

        final Consumer<Object> c = new Consumer<Object>() {
            boolean done = false;

            @Override
            public void accept(Object t) {
                if (!done) {
                    func.apply(t);
                    done = true;
                }
            }
        };
        return c;
    }
}